home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacFormat España 15
/
macformat_15.iso
/
Shareware Internet
/
Desarrolladores
/
gray image 2.1
/
read_xwd.cc
< prev
next >
Wrap
Text File
|
1995-10-08
|
12KB
|
403 lines
// This may look like C code, but it is really -*- C++ -*-
/*
************************************************************************
*
* Grayscale Image
*
* Read an image from the X Window dump file
*
* $Id: read_xwd.cc,v 2.0 1995/03/09 15:23:17 oleg Exp oleg $
*
************************************************************************
*/
#include "image.h"
#include "endian_io.h"
#include "x11wd.h"
#include <iostream.h>
/*
*------------------------------------------------------------------------
* Create an image from the file
* This function attempt to determine the image file format by looking at
* the first two bytes of the file. They are
* 'Px' - for a Portable GrayMap
* 'MM' or 'II' - for a TIFF file
* otherwise, it _might_ be an X window dump.
* After the file format is guessed, the program calls an appropriate
* reader to actually load the file.
*/
IMAGE::IMAGE(const char * file_name, const bool print_header_info)
{
message("\nReading the file '%s' ",file_name);
EndianIn file(file_name);
assert( file.good() );
char byte1 = file.peek();
if( byte1 == 'P' )
read_pgm(file,print_header_info);
else if( byte1 == 'M' || byte1 == 'I' )
read_tiff(file,print_header_info);
else
read_xwd(file,print_header_info);
}
/*
*------------------------------------------------------------------------
* Class XWDump
* designed to contain the control info about the image
* as defined in the X Window Dump file
*/
class XWDump // All the info pertaining to the XWD file
: public X11WDFileHeader, public EndianIn
{
public:
char * win_name; // Name of the image in the file
XWDump(EndianIn& file); // Constructor
void info(void) const; // Dump the header information
void read_in_pixel_map(IMAGE& image); // Reading the pixmap into image
};
/*
*------------------------------------------------------------------------
* Construct the XWDump
* by reading the header of the X Window dump file
*/
XWDump::XWDump(EndianIn& file) : EndianIn(file)
{
streampos beg_of_file = EndianIn::tellg(); // Remember the curr position
set_bigendian(); // Try reading a magic byte in one order
header_size = read_long("Reading the header_size");
file_version = read_long("Reading the XWD file version");
if( file_version != X11WD_FILE_VERSION )
{
set_littlendian(); // Try now another byte order
EndianIn::seekg(beg_of_file);
header_size = read_long("Reading the header_size");
file_version = read_long("Reading the XWD file version");
}
assure( file_version == X11WD_FILE_VERSION,
"I have tried different byte orders but failed to read\nthe XWD "
"file version correctly" );
assure( header_size >= sizeof(X11WDFileHeader),"XWD header is too small" );
// Read the rest of the header
pixmap_format = read_long("Reading the pixmap_format");
pixmap_depth = read_long("Reading the pixmap_depth");
pixmap_width = read_long("Reading the pixmap_width");
pixmap_height = read_long("Reading the pixmap_height");
xoffset = read_long("Reading the xoffset");
xbyte_order = read_long("Reading the byte_order");
bitmap_unit = read_long("Reading the bitmap_unit");
bitmap_bit_order = read_long("Reading the bitmap_bit_order");
bitmap_pad = read_long("Reading the bitmap_pad");
bits_per_pixel = read_long("Reading the bits_per_pixel");
bytes_per_line = read_long("Reading the bytes_per_line");
visual_class = read_long("Reading the visual_class");
red_mask = read_long("Reading the red_mask");
green_mask = read_long("Reading the green_mask");
blue_mask = read_long("Reading the blue_mask");
bits_per_rgb = read_long("Reading the bits_per_rgb");
colormap_entries = read_long("Reading the colormap_entries");
ncolors = read_long("Reading the ncolors");
window_width = read_long("Reading the window_width");
window_height = read_long("Reading the window_height");
window_x = read_long("Reading the window_x");
window_y = read_long("Reading the window_y");
window_bdrwidth = read_long("Reading the window_bdrwidth");
// Read the window name
register int len = header_size - sizeof(X11WDFileHeader);
win_name = new char[len];
if( !EndianIn::read(win_name, len) )
error("Error reading the window name");
if( ncolors > 0 ) // Skip the Xcolors
EndianIn::seekg(ncolors*sizeof(X11XColor),ios::cur);
}
/*
*------------------------------------------------------------------------
* Print out all the control information pertaining to the
* X Window Image read
*/
void XWDump::info(void) const
{
cout << "\n\n=====>The following X Window dump has been read";
cout << "\nVersion: " << file_version;
cout << "\nPixmap format: ";
switch(pixmap_format)
{
case XYBitmap:
cout << "XYBitmap";
break;
case XYPixmap:
cout << "XYPixmap";
break;
case ZPixmap:
cout << "ZPixmap";
break;
default:
_error("Unknown pixel format: %d",pixmap_format);
}
cout << "\nPixmap depth: " << pixmap_depth;
cout << "\nPixmap width: " << pixmap_width;
cout << "\nPixmap height: " << pixmap_height;
cout << "\nBitmap x offs: " << xoffset;
cout << "\nByte order: " << ( xbyte_order == MSBFirst ?
"MSBFirst" : "LSBFirst" );
cout << "\nBitmap unit: " << bitmap_unit;
cout << "\nBitmap bitOrder:" << ( bitmap_bit_order == MSBFirst ?
"MSBFirst" : "LSBFirst" );
cout << "\nScanline pad: " << bitmap_pad;
cout << "\nBits per pixel: " << bits_per_pixel;
cout << "\nBytes per line: " << bytes_per_line;
cout << "\nVisual class: ";
switch(visual_class)
{
case StaticGray:
cout << "StaticGray";
break;
case GrayScale:
cout << "GrayScale";
break;
case StaticColor:
cout << "StaticColor";
break;
case PseudoColor:
cout << "PseudoColor";
break;
case TrueColor:
cout << "TrueColor";
break;
case DirectColor:
cout << "DirectColor";
break;
default:
_error("Unknown visual class: %d",visual_class);
}
cout << "\nZ red mask: 0x" << ::hex << red_mask;
cout << "\nZ green mask: 0x" << ::hex << green_mask;
cout << "\nZ blue mask: 0x" << ::hex << blue_mask << ::dec;
cout << "\nBits per rgb: " << bits_per_rgb;
cout << "\nColormap items: " << colormap_entries;
cout << "\nNo. colors: " << ncolors;
cout << "\nWindow width: " << window_width;
cout << "\nWindow height: " << window_height;
cout << "\nWindow left X: " << window_x;
cout << "\nWindow upper Y: " << window_y;
cout << "\nWindow border: " << window_bdrwidth;
cout << "\nWindow name: " << win_name;
cout << "\n-----End of X Window dump information" << endl;
}
/*
*------------------------------------------------------------------------
* Read the image pixmap and write it into the image
*/
// Load image from a Gray scale pixelmap
// of depth 8 (that is, pixel matrix
// arranged row-by-row)
class load_8bit_pixmap : public PixelPrimAction
{
EndianIn& ins;
void operation(GRAY& pixel)
{ pixel = ins.read_byte("Reading the pixel map"); }
public:
load_8bit_pixmap(EndianIn& _ins) : ins(_ins)
{ message("\nReading the gray scale pixel map of depth 8..."); }
};
// Try to load arbitrary pixel map from the
// XWD file, doing pixel unpacking (and
// conversion from rgb to the grayscale)
// if necessary
class load_any_pixmap : public PixelAction
{
const int pixel_mask; // Parameters of the pixel map
const int bits_per_pixel; // (cached from XWDump header)
const int bits_per_item;
const int bit_order;
bool convert_rgb;
EndianIn& ins;
char * scanline;
char * scanline_end;
// Used in pixel unpacking
char *cp; // Current scanline ptr
long int bits_storage;
int bit_shift;
int remains_bit;
void load_scanline(void);
void operation(GRAY& pixel);
public:
load_any_pixmap(XWDump& header);
virtual ~load_any_pixmap(void) { delete scanline; }
};
// Prepare for loading pixelmap, initialize
// param cacje and bit cache
load_any_pixmap::load_any_pixmap(XWDump& header)
: pixel_mask(( 1 << header.bits_per_pixel ) - 1),
bits_per_pixel( header.bits_per_pixel ),
bits_per_item( header.bitmap_unit ),
bit_order( header.bitmap_bit_order ),
convert_rgb( header.visual_class == TrueColor ||
header.visual_class == DirectColor ),
ins(header),
bits_storage(0), bit_shift(0), remains_bit(0)
{
scanline = new char[header.bytes_per_line];
scanline_end = scanline + header.bytes_per_line;
cp = &scanline[0];
if( convert_rgb )
message("\nA colored image with direct RGB specification\n"
"is to be converted to gray scale\n");
}
void load_any_pixmap::load_scanline(void)
{
switch( bits_per_item ) // Read a scanline
{
case 8:
{
for(register char *p = (char *)scanline; p < (char*)scanline_end;)
*p++ = ins.read_byte("Reading the scanline");
}
break;
case 16:
{
for(register short *p = (short *)scanline; p < (short*)scanline_end;)
*p++ = ins.read_short("Reading the scanline");
}
break;
case 32:
{
for(register long *p = (long *)scanline; p < (long*)scanline_end;)
*p++ = ins.read_long("Reading the scanline");
}
break;
default:
assure(0,"can't happen");
}
assert( row == 0 || cp == scanline_end );
cp = &scanline[0];
bits_storage = 0;
bit_shift = 0;
remains_bit = 0;
}
// Load the current (row,col) pixel
void load_any_pixmap::operation(GRAY& pixel)
{
if( col == 0 )
load_scanline();
if( remains_bit == 0 )
{
switch(bits_per_item)
{
case 8:
bits_storage = *cp;
break;
case 16:
bits_storage = *((short int *)cp);
break;
case 32:
bits_storage = *((long int *)cp);
break;
}
cp += bits_per_item/8;
remains_bit = bits_per_item;
bit_shift = ( bit_order == MSBFirst ? bits_per_item - bits_per_pixel :
0 );
}
assert( bit_shift >= 0 );
register unsigned int raw_pixel = ( bits_storage >> bit_shift ) & pixel_mask;
bit_shift += ( bit_order == MSBFirst ? - bits_per_pixel :
bits_per_pixel );
remains_bit -= bits_per_pixel;
assure(remains_bit >= 0,"Something goes wrong with bits conversion");
if(convert_rgb)
pixel = ((raw_pixel & 0xff0000) << (20-16)) + /* Red part */
((raw_pixel & 0xff00) << (10-8)) + /* Green part */
((raw_pixel & 0xff)); /* Blue part */
else
pixel = raw_pixel;
}
// Analyse the header and figure out if
// we can handle the XWdump we've read.
// Then set out to read the pixelmap
// using the best strategy
void XWDump::read_in_pixel_map(IMAGE& image)
{
const int bits_per_item = bitmap_unit;
if( pixmap_depth > 24 )
_error("can't handle X11 pixmap_depth %d greater than 24",pixmap_depth);
if( bits_per_rgb > 24 )
_error("can't handle X11 bits_per_rgb > 24");
if( pixmap_format != ZPixmap && pixmap_depth != 1 )
_error("can't handle X11 pixmap_format %d with depth != 1",pixmap_format);
if( bits_per_item != 8 && bits_per_item != 16 && bits_per_item != 32 )
_error("X11 bitmap_unit (%d) is non-standard - can't handle",
bits_per_item);
if( bits_per_item == 8 && bits_per_pixel == 8 &&
visual_class != TrueColor && visual_class != DirectColor )
image.apply(load_8bit_pixmap(*this));
#if 0
else if( bits_per_item == 8 && bits_per_pixel == 1 )
pixmap_type = PT_BlackWhite;
#endif
else
image.apply(load_any_pixmap(*this));
}
/*
*========================================================================
* Root module - actual IMAGE constructor
*/
void IMAGE::read_xwd(EndianIn& file, const bool print_header_info)
{
message("Reading the X window dump image\n");
XWDump xwdump(file);
if( print_header_info )
xwdump.info();
allocate(xwdump.pixmap_height,xwdump.pixmap_width,xwdump.bits_per_pixel);
name = xwdump.win_name;
xwdump.read_in_pixel_map(*this);
message("\n%dx%dx%d image '%s' has been read\n",ncols,nrows,
bits_per_pixel,name);
}